package com.jilefojing.session.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.jilefojing.beans.constant.Constants;
import com.jilefojing.beans.constant.DictionaryConstants;
import com.jilefojing.beans.data.enums.ResponseEnum;
import com.jilefojing.beans.enums.PlatformEnum;
import com.jilefojing.beans.enums.ServerTypeEnum;
import com.jilefojing.beans.enums.forusersession.StatusEnumForUserSession;
import com.jilefojing.beans.enums.forusersession.TypeEnumForUserSession;
import com.jilefojing.beans.exception.UserContextException;
import com.jilefojing.beans.exception.UserTokenException;
import com.jilefojing.beans.pojos.Dictionary;
import com.jilefojing.beans.pojos.UserSession;
import com.jilefojing.beans.pojos.enhanced.EnhancedUser;
import com.jilefojing.beans.pojos.enhanced.EnhancedUserSession;
import com.jilefojing.context.beans.vo.RememberMe;
import com.jilefojing.context.beans.vo.UserContext;
import com.jilefojing.context.beans.vo.UserToken;
import com.jilefojing.dao.IUserSessionDao;
import com.jilefojing.service.IDictionaryService;
import com.jilefojing.service.IUserService;
import com.jilefojing.service.base.impl.BaseService;
import com.jilefojing.session.service.ILoginService;
import com.jilefojing.session.service.ILogoutService;
import com.jilefojing.session.service.IUserContextService;
import com.jilefojing.session.service.IUserSessionService;
import com.jilefojing.util.AESCoder;
import com.jilefojing.util.Detect;
import com.jilefojing.util.UserTokenUtil;

/**
 * 
 * @author jgshun
 * 
 */
@Service("up5UserSessionService")
public class UserSessionService extends BaseService<UserSession> implements IUserSessionService {
	public final static int DEFAULT_VALID_MINUTE = 30;
	public final static int DEFAULT_APP_VALID_MINUTE = 525600;
	public final static long DEFAULT_REFRESH_TIME = DEFAULT_VALID_MINUTE * 60 * 1000 * 9 / 10;

	private final static Logger _LOGGER = LoggerFactory.getLogger(UserSessionService.class);

	@Autowired
	private IUserContextService userContextService;
	@Autowired
	private IUserSessionDao userSessionDao;
	@Autowired
	private IUserService userService;
	@Autowired
	private IDictionaryService dictionaryService;
	@Autowired
	private ILogoutService logoutService;
	@Autowired
	private ILoginService loginService;

	@Override
	public EnhancedUserSession save(UserSession userSession) {
		userSession = super.save(userSession, null);

		EnhancedUserSession enhancedUserSession = new EnhancedUserSession(userSession);
		enhancedUserSession.setId(userSession.getId());
		this.addUserContextToSession(enhancedUserSession);
		return enhancedUserSession;
	}

	@Override
	public EnhancedUserSession generateEnhancedUserSession(long userId, TypeEnumForUserSession type, String deviceId, PlatformEnum platform, boolean isRM, Map<String, Object> extralParam)
			throws UserContextException {

		EnhancedUserSession enhancedUserSession = new EnhancedUserSession();
		Date date = new Date();
		enhancedUserSession.setTime(date);
		enhancedUserSession.setUpdateTime(date);
		if (platform == PlatformEnum.ANDROID || platform == PlatformEnum.IPHONE) {
			enhancedUserSession.setValidMinute(DEFAULT_APP_VALID_MINUTE);
		} else {
			enhancedUserSession.setValidMinute(DEFAULT_VALID_MINUTE);
		}

		enhancedUserSession.setPlatform(platform);
		enhancedUserSession.setType(type);
		enhancedUserSession.setDeviceId(deviceId);
		enhancedUserSession.setStatus(StatusEnumForUserSession.VALID);

		EnhancedUser _sessionEnhancedUser = null;
		if (isRM) {
			EnhancedUser _EnhancedUser = userService.getEnhancedUser(userId);
			_sessionEnhancedUser = new EnhancedUser();
			_sessionEnhancedUser.setId(_EnhancedUser.getId());
			_sessionEnhancedUser.setPassword(_EnhancedUser.getPassword());
		} else {
			_sessionEnhancedUser = new EnhancedUser();
			_sessionEnhancedUser.setId(userId);
		}

		enhancedUserSession.setEnhancedUser(_sessionEnhancedUser);

		try {

			enhancedUserSession.setSecretKey(AESCoder.initKeyString());
			UserToken userToken = UserTokenUtil.generateUserToken(isRM, enhancedUserSession);

			enhancedUserSession.setUid(userToken.getUid());
			enhancedUserSession.setToken(userToken.getToken());
			enhancedUserSession.setSign(userToken.getSign());
		} catch (Exception e) {
			_LOGGER.error(e.getMessage(), e);
			throw new UserContextException("[保存用户SESSION异常--生成TOKEN异常]:" + e.getMessage());
		}

		if (Detect.notEmpty(extralParam)) {
			enhancedUserSession.setIp(extralParam.get("ip").toString());
			String ua = extralParam.get("user-agent").toString();
			if (Detect.notEmpty(ua) && ua.length() < 501) {
				enhancedUserSession.setUa(ua);
			}
			enhancedUserSession.setCredentialsToLog(extralParam.get(Constants.CREDENTIALS_TO_LOG_KEY).toString());
		}

		// try {
		// HttpServletRequest request = ((ServletRequestAttributes)
		// RequestContextHolder
		// .getRequestAttributes()).getRequest();
		// if (request != null) {
		// enhancedUserSession.setIp(request.getRemoteAddr());
		// String ua = request.getHeader("user-agent");
		// if (Detect.notEmpty(ua) && ua.length() < 501) {
		// enhancedUserSession.setUa(ua);
		// }
		// String credentialsToLog =
		// request.getParameter(Constants.CREDENTIALS_TO_LOG_KEY);
		// enhancedUserSession.setCredentialsToLog(credentialsToLog);
		// }
		// } catch (Exception e) {
		// _LOGGER.error("获取REQUEST异常:" + e.getMessage(), e);
		// }

		return enhancedUserSession;
	}

	@Override
	public UserSession convetnEnhancedUserSessionToUserSession(EnhancedUserSession enhancedUserSession) {
		UserSession userSession = new UserSession();
		userSession.setCredentialsToLog(enhancedUserSession.getCredentialsToLog());
		userSession.setDeviceId(enhancedUserSession.getDeviceId());
		// userSession.setId(enhancedUserSession.getId());
		userSession.setIp(enhancedUserSession.getIp());
		userSession.setOfflineMsg(enhancedUserSession.getOfflineMsg());
		userSession.setOfflineMsgMinute(enhancedUserSession.getOfflineMsgMinute());
		userSession.setOfflineTime(enhancedUserSession.getOfflineTime());
		userSession.setPlatform(enhancedUserSession.getPlatform().getValue());
		userSession.setSecretKey(enhancedUserSession.getSecretKey());
		userSession.setSign(enhancedUserSession.getSign());
		userSession.setStatus((int) enhancedUserSession.getStatus().getCode());
		userSession.setTime(enhancedUserSession.getTime());
		userSession.setToken(enhancedUserSession.getToken());
		userSession.setUa(enhancedUserSession.getUa());
		userSession.setUid(enhancedUserSession.getUid());
		userSession.setUpdateTime(enhancedUserSession.getUpdateTime());
		userSession.setUserId(enhancedUserSession.getEnhancedUser().getId());
		userSession.setValidMinute(enhancedUserSession.getValidMinute());

		return userSession;
	}

	@Override
	public UserContext loadSessionUserContext(UserToken userToken) throws UserContextException {
		UserContext sessionUserContext = null;

		if (!Detect.notEmpty(userToken.getUid())) {
			throw new UserContextException(ResponseEnum.NO_LOGIN);
		}

		boolean isRM = false;// 是否记住密码
		EnhancedUserSession enhancedUserSession = this.getEnhancedUserSessionByUid(userToken.getUid());
		if (enhancedUserSession == null && (userToken.getRm() == null || !userToken.getRm().isRm())) {
			throw new UserContextException(ResponseEnum.NO_LOGIN);
		}
		if (enhancedUserSession == null) {
			enhancedUserSession = userToken.getRm().getSer();
			isRM = true;
		}

		try {
			UserTokenUtil.checkUserToken(userToken, enhancedUserSession);
		} catch (UserTokenException e) {
			UserContextException userContextException = new UserContextException(e.getMessage());
			userContextException.setException(e);
			throw userContextException;
		}

		this.checkPasswordReset(enhancedUserSession);// 校验密码是否被修改过

		if (isRM) {
			sessionUserContext = new UserContext();
			sessionUserContext.setEnhancedUserSession(loginService.loginByRemeberMe(userToken.getRm(), null));
		} else {
			try {
				if (sessionUserContext == null) {
					sessionUserContext = this.addUserContextToSession(enhancedUserSession);
				}
			} catch (Exception e) {
				sessionUserContext = new UserContext();
				sessionUserContext.setEnhancedUserSession(enhancedUserSession);
				_LOGGER.error("[保存用户SESSION异常]:" + e.getMessage(), e);
			}
		}

		return sessionUserContext;
	}

	private void checkPasswordReset(EnhancedUserSession enhancedUserSession) throws UserContextException {
		String _pwd = enhancedUserSession.getEnhancedUser().getPassword();
		EnhancedUser enhancedUserInfo = userService.getEnhancedUser(enhancedUserSession.getEnhancedUser().getId());
		String _dbPwd = enhancedUserInfo.getPassword();
		if (!Detect.notEmpty(_pwd) && !Detect.notEmpty(_dbPwd)) {
		} else if (!Detect.notEmpty(_pwd) && Detect.notEmpty(_dbPwd)) {
			throw new UserContextException(ResponseEnum.PASSWORD_CHANGE);
		} else if (Detect.notEmpty(_pwd) && !Detect.notEmpty(_dbPwd)) {
			throw new UserContextException(ResponseEnum.PASSWORD_CHANGE);
		} else {
			EnhancedUserSession _EnhancedUserSession = new EnhancedUserSession();
			EnhancedUser _EnhancedUser = new EnhancedUser();
			_EnhancedUser.setId(enhancedUserInfo.getId());
			_EnhancedUser.setPassword(_dbPwd);
			_EnhancedUserSession.setEnhancedUser(_EnhancedUser);
			_EnhancedUserSession.setSecretKey(enhancedUserSession.getSecretKey());

			try {
				RememberMe _RememberMe = UserTokenUtil.generateRememberMe(_EnhancedUserSession);
				if (!_RememberMe.getSer().getEnhancedUser().getPassword().equals(_pwd)) {
					throw new UserContextException(ResponseEnum.PASSWORD_CHANGE);
				}
			} catch (Exception e) {
				_LOGGER.error(e.getMessage(), e);
				throw new UserContextException("未登录:" + e.getMessage());
			}
		}
	}

	@Override
	public EnhancedUserSession getEnhancedUserSessionByUid(String uid) throws UserContextException {

		EnhancedUserSession enhancedUserSession = null;

		UserSession userSession = userSessionDao.getByUid(uid);
		if (userSession == null) {
			return null;
		} else {
			enhancedUserSession = new EnhancedUserSession(userSession);
			EnhancedUser _EnhancedUser = userService.getEnhancedUser(enhancedUserSession.getEnhancedUser().getId());
			enhancedUserSession.getEnhancedUser().setPassword(_EnhancedUser.getPassword());
			try {
				RememberMe _RememberMe = UserTokenUtil.generateRememberMe(enhancedUserSession);
				enhancedUserSession.getEnhancedUser().setPassword(_RememberMe.getSer().getEnhancedUser().getPassword());
			} catch (Exception e) {
				_LOGGER.error("[生成REMEMBERME异常]:" + e.getMessage(), e);
			}

		}

		if (enhancedUserSession.getStatus() == StatusEnumForUserSession.OFFLINE) {
			PlatformEnum platform = PlatformEnum.getPlatformEnumByValue(enhancedUserSession.getPlatform().getValue());

			if (platform == PlatformEnum.PC || platform == PlatformEnum.WAP) {
				HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
				HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
				if (response == null) {
					response = (HttpServletResponse) request.getAttribute(Constants._WEB_LOCAL_RESPONSE);
				}
				UserTokenUtil.clearUserTokenFromCookie(request, response);
			}

			HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
			request.setAttribute("_OTHER_DEVICE_LOGIN_EX", ResponseEnum.OTHER_DEVICE_LOGIN.getMsg());

			throw new UserContextException(ResponseEnum.OTHER_DEVICE_LOGIN);
		}

		return enhancedUserSession;
	}

	@Override
	public void deleteByUid(String uid) {
		userSessionDao.deleteByUid(uid);
	}

	@Override
	public void refreshSessionExpireByUid(String uid) {
		// UserContext sessionUserContext = null;
		// Date nowDate = new Date();

		// long validTime =
		// sessionUserContext.getEnhancedUserSession().getUpdateTime().getTime()
		// + DEFAULT_VALID_MINUTE * 60 * 1000;

		// if ((validTime - nowDate.getTime()) <= DEFAULT_REFRESH_TIME) {
		// _LOGGER.info(nowDate +
		// "========================REFRESH_SESSION_EXPIRE============================="
		// + sessionUserContext.getEnhancedUserSession().getUpdateTime());
		// sessionUserContext.getEnhancedUserSession().setUpdateTime(nowDate);

		this.refreshUpdateTimeByUid(uid);
		// }
	}

	private void refreshUpdateTimeByUid(String uid) {
		UserSession userSession = userSessionDao.getByUid(uid);
		userSession.setUpdateTime(new Date());
		userSessionDao.updateByPrimaryKeySelective(userSession);
	}

	@Override
	public UserContext addUserContextToSession(EnhancedUserSession enhancedUserSession) {
		ServerTypeEnum serverType = enhancedUserSession.getPlatform() == PlatformEnum.PC ? ServerTypeEnum.jilefojing_WEB
				: enhancedUserSession.getPlatform() == PlatformEnum.WAP ? ServerTypeEnum.jilefojing_WAP : enhancedUserSession.getPlatform() == PlatformEnum.ANDROID ? ServerTypeEnum.jilefojing_APP
						: enhancedUserSession.getPlatform() == PlatformEnum.IPHONE ? ServerTypeEnum.jilefojing_APP : ServerTypeEnum.jilefojing_WEB;

		UserContext userContext = null;
		try {
			UserToken userToken = new UserToken(enhancedUserSession);
			if (!Detect.notEmpty(userToken.getSign()) || !Detect.notEmpty(userToken.getToken()) || !Detect.notEmpty(userToken.getUid()) || userToken.getTime() == null) {
				throw new UserTokenException("[USERTOKEN属性不能有空值]");
			}
			userContext = userContextService.loadUserContext(enhancedUserSession.getEnhancedUser().getId(), serverType);
			enhancedUserSession.getEnhancedUser().setPassword(userContext.getEnhancedUser().getPassword());
			try {
				RememberMe _RememberMe = UserTokenUtil.generateRememberMe(enhancedUserSession);
				enhancedUserSession.getEnhancedUser().setPassword(_RememberMe.getSer().getEnhancedUser().getPassword());
			} catch (Exception e) {
				_LOGGER.error("[生成REMEMBERME异常]:" + e.getMessage(), e);
			}
			userContext.setEnhancedUserSession(enhancedUserSession);
		} catch (Exception e) {
			_LOGGER.error("[保存用户SESSION异常]:" + e.getMessage(), e);
		}
		return userContext;
	}

	@Override
	public List<EnhancedUserSession> getEnhancedUserSessionForUserByStatus(long userId, List<StatusEnumForUserSession> statuses) {
		List<UserSession> userSessions = userSessionDao.getForUserByStatus(userId, statuses);
		if (!Detect.notEmpty(userSessions)) {
			return null;
		}
		return this.conventUserSessionsToEnhancedUserSessions(userSessions);
	}

	@Override
	public List<EnhancedUserSession> conventUserSessionsToEnhancedUserSessions(List<UserSession> userSessions) {
		List<EnhancedUserSession> enhancedUserSessions = new ArrayList<EnhancedUserSession>();
		for (UserSession _UserSession : userSessions) {
			enhancedUserSessions.add(new EnhancedUserSession(_UserSession));
		}
		return enhancedUserSessions;
	}

	@Override
	public void updateStatusByUids(StatusEnumForUserSession status, List<String> uids) {
		userSessionDao.updateStatusByUids(status, uids);
	}

	@Override
	public void updateUserSessionStatusForOnlyOneOnline(EnhancedUserSession curEnhancedUserSession) {
		Dictionary dictionary = dictionaryService.getByNodeName(DictionaryConstants.ONLY_ONE_ONLINE);
		if (dictionary != null && dictionary.getNode() != null && Integer.valueOf(dictionary.getNode()) == 1 && !Detect.notEmpty(curEnhancedUserSession.getCredentialsToLog())) {

			List<StatusEnumForUserSession> statuses = new ArrayList<StatusEnumForUserSession>();
			statuses.add(StatusEnumForUserSession.VALID);
			List<EnhancedUserSession> enhancedUserSessions = this.getEnhancedUserSessionForUserByStatus(curEnhancedUserSession.getEnhancedUser().getId(), statuses);

			if (Detect.notEmpty(enhancedUserSessions)) {
				this.excludeEnhancedUserSessions(enhancedUserSessions, curEnhancedUserSession);
				List<String> uids = new ArrayList<String>();
				for (EnhancedUserSession _EnhancedUserSession : enhancedUserSessions) {
					uids.add(_EnhancedUserSession.getUid());
				}
				if (Detect.notEmpty(uids)) {
					this.updateStatusByUids(StatusEnumForUserSession.OFFLINE, uids);
				}
			}
		}
	}

	private void excludeEnhancedUserSessions(List<EnhancedUserSession> enhancedUserSessions, EnhancedUserSession curEnhancedUserSession) {
		int size = enhancedUserSessions.size() - 1;
		for (int i = size; i > -1; i--) {
			EnhancedUserSession _EnhancedUserSession = enhancedUserSessions.get(i);
			if (_EnhancedUserSession.getUid().equals(curEnhancedUserSession.getUid()) || Detect.notEmpty(_EnhancedUserSession.getCredentialsToLog())) {
				enhancedUserSessions.remove(i);
			}
		}
	}
}
